
package ClientGraphics;

import GameEngine.GameConstants;
import GameEngine.GameConstants.Graphic;
import GameEngine.GameConstants.Levels;
import GameEngine.Vector;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 * This class will take in a GraphicObject and update its image.
 * This is essentially the library of images.
 * @author mhfowler
 */

public class LoadGraphic {

    private static final String dir = "Images/Sprites/"; // directory for images
    private static boolean randBool = false; // alternates back and forth
    public static final double PIX_BUFFER = 1.2;

    /**
     * Returns an image, loaded and rotated toward the proper direction.
     * @param name
     * @param direction // use null if one does not want to rotate
     * @return
     */

    public static ImageWrapper loadImage(String name, GraphicObject o) {
        BufferedImage loaded = null;

        loaded = loadImageHelper(dir + name);
        Vector direction = o.direction;
        Vector scale = o.size;
        // now scale image
        loaded = scaleImage(loaded, scale);
        ImageWrapper toReturn = new ImageWrapper(loaded, new Vector(0,0));
        // (1,0) is default direction
        if (!(direction.getX() == 1 && direction.getY() == 0))  {
            // if a rotation is desired
            double rads;
            // check if obtuse, in which case we need a work around for the fact that Math.acos returns angle between 0 and PI
            if (direction.getY() < 0) {
                // calculate the angle
                rads = getAngle(new Vector(-direction.getX(),direction.getY()));
                rads += Math.PI;
            }
            // otherwise its acute and its fine
            else
            {
                rads = getAngle(direction);
            }
            // rotate with angle
             toReturn = rotateImage(o, loaded, rads);
        }
        // now if its not the background, scale for pix buffer
        if (o.layer != 0)
        {
            //scaleImageWrapper(toReturn, PIX_BUFFER);
        }
        return toReturn;
    }

    public static void loadAnimation(GraphicObject o)
    {
        int numAnimations;
        ImageWrapper loaded;
        switch (o.current) {
            case BLUEPLAYER:
                numAnimations = 2;
                o.anim = new Animation(numAnimations, true);
                loaded = loadImage("stickfigure.gif", o);
                o.anim.addImage(loaded, 0);
                loaded = loadImage("stickfigure2.gif", o);
                o.anim.addImage(loaded, 1);
                break;
            case DEFAULTBACK:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, true);
                loaded = loadImage("default.gif", o);
                o.anim.addImage(loaded, 0);
                break;
            case PINKPLAYER_WALK:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                ImageWrapper frame1 = loadImage("001.png", o);
                ImageWrapper frame2 = loadImage("002.png", o);
                ImageWrapper frame3 = loadImage("003.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case PINKPLAYER_STAY:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("001.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case PINKPLAYER_JUMP:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("004.png", o);
                frame2 = loadImage("005.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case GREENPLAYER_WALK:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("101.png", o);
                frame2 = loadImage("102.png", o);
                frame3 = loadImage("103.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case GREENPLAYER_STAY:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("101.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case GREENPLAYER_JUMP:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("104.png", o);
                frame2 = loadImage("105.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case REDPLAYER_WALK:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("201.png", o);
                frame2 = loadImage("202.png", o);
                frame3 = loadImage("203.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case REDPLAYER_STAY:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("201.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case REDPLAYER_JUMP:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("204.png", o);
                frame2 = loadImage("205.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case PURPLEPLAYER_WALK:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("301.png", o);
                frame2 = loadImage("302.png", o);
                frame3 = loadImage("303.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case PURPLEPLAYER_STAY:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("301.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case PURPLEPLAYER_JUMP:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("304.png", o);
                frame2 = loadImage("305.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case YELLOWPLAYER_WALK:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("401.png", o);
                frame2 = loadImage("402.png", o);
                frame3 = loadImage("403.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case YELLOWPLAYER_STAY:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("401.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case YELLOWPLAYER_JUMP:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("404.png", o);
                frame2 = loadImage("405.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case PINKPLAYER_WALKLEFT:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("011.png", o);
                frame2 = loadImage("012.png", o);
                frame3 = loadImage("013.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case PINKPLAYER_STAYLEFT:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("011.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case PINKPLAYER_JUMPLEFT:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("014.png", o);
                frame2 = loadImage("015.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
             case GREENPLAYER_WALKLEFT:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("111.png", o);
                frame2 = loadImage("112.png", o);
                frame3 = loadImage("113.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case GREENPLAYER_STAYLEFT:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("111.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case GREENPLAYER_JUMPLEFT:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("114.png", o);
                frame2 = loadImage("115.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case REDPLAYER_WALKLEFT:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("211.png", o);
                frame2 = loadImage("212.png", o);
                frame3 = loadImage("213.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case REDPLAYER_STAYLEFT:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("211.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case REDPLAYER_JUMPLEFT:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("214.png", o);
                frame2 = loadImage("215.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case PURPLEPLAYER_WALKLEFT:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("311.png", o);
                frame2 = loadImage("312.png", o);
                frame3 = loadImage("313.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case PURPLEPLAYER_STAYLEFT:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("311.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case PURPLEPLAYER_JUMPLEFT:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("314.png", o);
                frame2 = loadImage("315.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case YELLOWPLAYER_WALKLEFT:
                // layering
                o.layer = 2;
                numAnimations = 8;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("411.png", o);
                frame2 = loadImage("412.png", o);
                frame3 = loadImage("413.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                o.anim.addImage(frame2, 6);
                o.anim.addImage(frame2, 7);
                break;
            case YELLOWPLAYER_STAYLEFT:
                // layering
                o.layer = 2;
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("411.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case YELLOWPLAYER_JUMPLEFT:
                // layering
                o.layer = 2;
                numAnimations = 3;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("414.png", o);
                frame2 = loadImage("415.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                break;
            case ICE:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                if (randBool) {
                    frame1 = loadImage("ice01.png", o);
                } else {
                    frame1 = loadImage("ice02.png", o);
                }
                randBool = !randBool;
                o.anim.addImage(frame1, 0);
                break;
            case PORTAL:
                numAnimations = 6;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("portal01.png", o);
                frame2 = loadImage("portal02.png", o);
                frame3 = loadImage("portal03.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                break;
            case MUSHROOM:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("mush.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case WIND:
                numAnimations = 6;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("wind01.png", o);
                frame2 = loadImage("wind02.png", o);
                frame3 = loadImage("wind03.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                break;
            case FAN:
                numAnimations = 6;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("fan01.png", o);
                frame2 = loadImage("fan02.png", o);
                frame3 = loadImage("fan03.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                break;
            case VACUUM:
                numAnimations = 6;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("fan03.png", o);
                frame2 = loadImage("fan02.png", o);
                frame3 = loadImage("fan01.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                o.anim.addImage(frame3, 4);
                o.anim.addImage(frame3, 5);
                break;
            case SPAWN_POINT:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("spawn.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case GOAL_POINT:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("goal.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case CHOMPERS:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("chompers.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case SPOUT:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("spout.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case WALL:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("wall.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case WATER:
                numAnimations = 4;
                o.anim = new Animation(numAnimations, true);
                if (randBool) {
                    frame1 = loadImage("water01.png", o);
                    frame2 = loadImage("water02.png", o);
                } else {
                    frame1 = loadImage("water02.png", o);
                    frame2 = loadImage("water03.png", o);
                }
                randBool = !randBool;
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame1, 1);
                o.anim.addImage(frame2, 2);
                o.anim.addImage(frame2, 3);
                break;
            case META:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, true);
                frame1 = loadImage("invisible.gif", o);
                o.anim.addImage(frame1, 0);
                break;
            case GEORGEWASHINGTON:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("portal4.gif", o);
                o.anim.addImage(frame1, 0);
                break;
            case PINKWALL:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("pinkwall.gif", o);
                o.anim.addImage(frame1, 0);
                break;
            case JAMESBROWN:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("jb.jpg", o);
                o.anim.addImage(frame1, 0);
                break;
            case FISH:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("fish01.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case BOMBDROP:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("fish02.png", o);
                o.anim.addImage(frame1, 0);
                break;
            case USESPECIAL:
                o.layer = 2;
                numAnimations = 5;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("flash01.png", o);
                frame2 = loadImage("flash02.png", o);
                frame3 = loadImage("flash03.png", o);
                ImageWrapper frame4 = loadImage("flash04.png", o);
                ImageWrapper frame5 = loadImage("flash05.png", o);
                o.anim.addImage(frame1, 0);
                o.anim.addImage(frame2, 1);
                o.anim.addImage(frame3, 2);
                o.anim.addImage(frame4, 3);
                o.anim.addImage(frame5, 4);
                break;
            case EINSTEIN:
                 numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("einstein.jpeg", o);
                o.anim.addImage(frame1, 0);
                break;
            case ABSTRACT:
                numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("abstraction.jpg", o);
                o.anim.addImage(frame1, 0);
                break;
            case CRAZY_COLORS:
               numAnimations = 1;
                o.anim = new Animation(numAnimations, false);
                frame1 = loadImage("Crazy_Colors.jpg", o);
                o.anim.addImage(frame1, 0);
                break;
            default:
                BufferedImage img = loadImageHelper(dir + "stickfigure.gif");
                ImageWrapper def = new ImageWrapper(img, o.minPos);
                o.anim = new Animation(1, true);
                o.anim.addImage(def, 0);
                break;
        }
    }

    /* this helper method takes in a filepath and loads that image */
    public static BufferedImage loadImageHelper(String imagePath) {
        BufferedImage toReturn = null;
        try {
            toReturn = ImageIO.read(new File(imagePath));
        } catch (IOException ex) {
           System.out.println("Library error, image filepath invalid.");
        }
        return toReturn;
    }


    ////////////////// TREATING BACKGROUNDS AS GRAPHIC ENUMERATIONS, FOR NOW ////////
    /* based on the name of the level, this method loads the background image,
     * or if name is unknown sets background to some default 
    public static BufferedImage loadBackground(Levels lev, IntVector size) {
        BufferedImage toReturn = null;
        // switch case based on name of level
           switch (lev) {
            case PIXRAIN:
                break;
            default:
                // white knit background
                toReturn = loadImageHelper("Images/knit.jpg");
                toReturn = scaleImage(toReturn, size);
                break;
        }

        return toReturn;
    }
    */



    public static GraphicObject loadBackground(Levels lev, Dimension levelSize) {
        GraphicObject background = new GraphicObject();
        background.minPos = new Vector(0, 0);
        background.size = new Vector(levelSize.width, levelSize.height);
        background.layer = 0;
        switch (lev) {
            case PIXRAIN:
                background.current = Graphic.JAMESBROWN;
                break;
            case GEORGEWASHINGTON:
                background.current = Graphic.GEORGEWASHINGTON;
                break;
            case EINSTEIN:
                background.current = Graphic.EINSTEIN;
                break;
            case ABSTRACT:    
                background.current = Graphic.ABSTRACT;
                break;
            case CRAZY_COLORS:
                background.current = Graphic.CRAZY_COLORS;
                break;
            default:
                background.current = Graphic.DEFAULTBACK;
                break;
        }
        return background;
    }



    /* this helper mehtod takes in a buffered image and the vector of how big it ought
     * to be, and rescales the image if it needs to be rescaled. */
    private static BufferedImage scaleImage(BufferedImage loaded, Vector size) {
        int width = (int) size.getX();
        int height = (int) size.getY();
        // create new image of correct size
        BufferedImage toReturn = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        // Paint scaled version of image to new image
        Graphics2D graphics2D = toReturn.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        graphics2D.drawImage(loaded, 0, 0, width, height, null);
        graphics2D.dispose();
        // return
        return toReturn;
    }

    private static BufferedImage scaleImage(BufferedImage loaded, int width, int height) {
        return scaleImage(loaded, new Vector(width, height));
    }

    private static BufferedImage scaleImage(BufferedImage loaded, double scaleFactor) {
        return scaleImage(loaded, (int) scaleFactor*loaded.getWidth(), (int) scaleFactor*loaded.getHeight());
    }


    /* takes in a vector representing the direction an object is facing, and returns the angle that this
     * direction is offset from a default of (1,0) */
    public static double getAngle(Vector direction) {
        Vector defaultVector = new Vector(1,0);
        return defaultVector.getTheta(direction);
    }


    /* rotate method which prevents image from getting cutoff during rotation */
    public static ImageWrapper rotateImage(GraphicObject o, BufferedImage img, double rads) {
        ImageWrapper newWrapper;
        double oldSize = Math.sqrt(img.getHeight()*img.getHeight() + img.getWidth()*img.getWidth());
        // create buffered image with dimensions equal to the diagonal of the source image
        BufferedImage toReturn = new BufferedImage((int)oldSize, (int)oldSize, BufferedImage.TYPE_INT_ARGB);
        // find difference between sizes using pythagorean theorem
        double newSize = Math.sqrt(oldSize*oldSize + oldSize*oldSize);
        int gapx = (int) ((toReturn.getWidth() - img.getWidth())/2.0);
        int gapy = (int) ((toReturn.getHeight() - img.getHeight())/2.0);
        // now rotate image
        AffineTransform tx = new AffineTransform();
        tx.setToTranslation(gapx, gapy);
        tx.rotate(rads, img.getWidth()/2, img.getHeight()/2);
        // return
        Graphics2D g = toReturn.createGraphics();
        g.drawImage(img, tx, null);
        // translate new image
        newWrapper = new ImageWrapper(toReturn, new Vector(-gapx, -gapy));
        return  newWrapper;
    }



    /* this is for adding extra pixels, such that actual game object size is less
     * than real size */
    public static void scaleImageWrapper(ImageWrapper wrapper, double k) 
    {
        // Load image to scale
        BufferedImage oldImage = wrapper.img;
        // size of old image
        Vector size = new Vector(oldImage.getWidth(), oldImage.getHeight());
        // size to scale to
        Vector newSize = size.scaleNew(k);
        // construct new image with new size
        BufferedImage newImage = scaleImage(wrapper.img, newSize);
        // offset calculation
        int xOff = (newImage.getWidth() - oldImage.getWidth())/2;
        int yOff = (newImage.getHeight() - oldImage.getHeight())/2;
        // apply offeset
        wrapper.xOffset -= xOff;
        wrapper.yOffset -= yOff;

        wrapper.img = newImage;

    }
}
